#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <memory>
#include "mock.h"
#include "md.h"

using namespace testing;
using namespace testing::ext;

class DemoTest : public testing::Test
{
public:
    static void SetUpTestSuite() {}
    static void TearDownTestSuite() {}
 protected:
    void SetUp()
    {
        SetMock(mock_.get());
        // set default call function
        EXPECT_CALL(*mock_, HcfMalloc(_, _)).WillRepeatedly(Invoke(__real_HcfMalloc));
        EXPECT_CALL(*mock_, OpensslEvpMdCtxSize(_)).WillRepeatedly(Invoke(__real_OpensslEvpMdCtxSize));
        EXPECT_CALL(*mock_, HcfIsClassMatch(_, _)).WillRepeatedly(Invoke(__real_HcfIsClassMatch));
        EXPECT_CALL(*mock_, HcfIsStrValid(_, _)).WillRepeatedly(Invoke(__real_HcfIsStrValid));
        EXPECT_CALL(*mock_, OpensslEvpDigestInitEx(_, _, _)).WillRepeatedly(Invoke(__real_OpensslEvpDigestInitEx));
    }
    void TearDown()
    {
        ResetMock();
    }

public:
    std::shared_ptr<HcfMock> mock_ = std::make_shared<HcfMock>();
};

HWTEST_F(DemoTest, DemoTest_001, TestSize.Level0)
{
    HcfMd *mdObj = nullptr;
    EXPECT_CALL(*mock_, HcfIsStrValid(_, _))
        .WillOnce(Return(false))
        .WillRepeatedly(Invoke(__real_HcfIsStrValid));
    HcfResult res = HcfMdCreate("SHA256", &mdObj);
    EXPECT_EQ(res, HCF_INVALID_PARAMS);

    EXPECT_CALL(*mock_, HcfMalloc(_, _))
        .WillOnce(Return(nullptr))
        .WillRepeatedly(Invoke(__real_HcfMalloc));
    res = HcfMdCreate("SHA256", &mdObj);
    EXPECT_EQ(res, HCF_ERR_MALLOC);

    EXPECT_CALL(*mock_, OpensslEvpDigestInitEx(_, _, _))
        .WillOnce(Return(0))
        .WillRepeatedly(Invoke(__real_OpensslEvpDigestInitEx));
    res = HcfMdCreate("SHA256", &mdObj);
    EXPECT_EQ(res, HCF_ERR_CRYPTO_OPERATION);

    res = HcfMdCreate("SHA256", &mdObj);
    EXPECT_EQ(res, HCF_SUCCESS);

    // uint8_t data[] = "hello";
    // HcfBlob inBlob = { data, sizeof(data)};
    // HcfBlob outBlob = {};
    // res = mdObj->update(mdObj, &inBlob);
    // EXPECT_EQ(res, HCF_SUCCESS);

    // res = mdObj->doFinal(mdObj, &outBlob);
    // EXPECT_EQ(res, HCF_SUCCESS);
    // HcfBlobDataFree(&outBlob);

    EXPECT_CALL(*mock_, OpensslEvpMdCtxSize(_))
        .WillOnce(Return(-1))
        .WillRepeatedly(Invoke(__real_OpensslEvpMdCtxSize));
    uint32_t len = mdObj->getMdLength(mdObj);
    EXPECT_EQ(len, 0);

    EXPECT_CALL(*mock_, OpensslEvpMdCtxSize(_))
        .WillOnce(Return(100))
        .WillRepeatedly(Invoke(__real_OpensslEvpMdCtxSize));
    len = mdObj->getMdLength(mdObj);
    EXPECT_EQ(len, 100);

    len = mdObj->getMdLength(mdObj);
    EXPECT_EQ(len, 32);

    EXPECT_CALL(*mock_, HcfIsClassMatch(_, _))
        .WillOnce(Return(false))
        .WillRepeatedly(Invoke(__real_HcfIsClassMatch));
    const char *name = mdObj->getAlgoName(mdObj);
    EXPECT_STREQ(name, nullptr);

    name = mdObj->getAlgoName(mdObj);
    EXPECT_STREQ(name, "SHA256");

    HcfObjDestroy(mdObj);
}
